import atlas
from itertools import *
from atlas import web, hdf, sql, util
from atlas.plotting import chart
from atlas.plotting.const import *
from mod454 import schema
from atlas.plotting import tracks
from atlas.plotting.tracks import prefab

SHOW_LABEL_LIMIT = 10000

def open_databases( conf ):
    """
    A helper function that returns handles to the hdf and sql databases
    """
    db = hdf.hdf_open( conf.HDF_DATABASE, mode='r' )
    session = sql.get_session( conf.SQL_URI )
    return db, session

def build_tracks( param, conf, data_label, fit_label, pred_label, strand, show=False ):
    """
    Builds tracks
    """
    
    # keeps track of the full execution time
    total = util.Tick()

    # gets all the labels for a fast lookup
    label_cache = web.label_cache( conf )       

    # keeps track on section execution times
    tick = util.Tick()

    # get database handles for hdf and sql
    db, session = open_databases( conf )

    # fetching x and y coordinates for bar and fit (line) for 
    # each strand plus (p), minus (m), all (a) 
    bix, bpy, bmy, bay = schema.hdf_query( db=db, name=data_label, param=param )
    fix, fpy, fmy, fay = schema.hdf_query( db=db, name=fit_label, param=param )

    # close the hdf database
    db.close()
    atlas.debug( 'HDF acccess time %s' % tick.tock() )

    # get all features within the range
    all = list( web.feature_query( session=session,  param=param ) )
    atlas.debug( 'SQL query time %s' % tick.tock() )

    # set the scale of the plot        
    param.xscale = [ param.start, param.end ] 

    # when visualizing on wide scales labels are not useful
    param.show_labels = ( param.end - param.start ) <= SHOW_LABEL_LIMIT

    # collect charts here        
    charts = []

    # this will cycle the background color for the tracks
    color = cycle( [LIGHT, WHITE] )

    # draws the barchart and the nucleosome chart below it
    if strand == 'composite':
        bar = prefab.composite_bartrack( fix=fix, fay=fay, bix=bix, bay=bay, param=param)
        nuc = prefab.composite_nuctrack( features=all, label=pred_label, param=param, kdict=label_cache, ylabel='H2A.Z' )    
    else:
        bar = prefab.twostrand_bartrack( fix=fix, fmy=fmy, fpy=fpy, bix=bix, bmy=bmy, bpy=bpy, param=param)
        nuc = prefab.twostrand_nuctrack( features=all, label=pred_label, param=param, kdict=label_cache )    
  
    charts.append( bar )            
    charts.append( nuc )            

    orf = prefab.orftrack ( features=all, label='ORF', param=param, kdict=label_cache, bgcolor=color.next() )
    charts.append( orf )
    
    # create the multiplot
    opt = chart_options( w=param.width )
    multi = chart.MultiChart(options=opt, charts=charts)
    atlas.debug( 'Multichart creation time %s' % tick.tock() )
    atlas.debug( 'Total plot creation time %s' % total.tock() )
    if show:   
        multi.show()

    return multi

def test( verbose=0 ):
    "Performs module level testing"
    import doctest
    doctest.testmod( optionflags=doctest.ELLIPSIS + doctest.NORMALIZE_WHITESPACE, verbose=verbose )

if __name__ == "__main__":
    from yeast import yeast_webconf as conf

    start = 1
    width = 2600
    chrom =  'chr01'
    end = start + width
    
    param = atlas.Param(start=start, end=end, chrom=chrom, width=800, nuc_track=1, orf_track=1, min_fit=2)

    #conf.composite_tracks( param=param, conf=conf, show=True )
    conf.twostrand_tracks( param=param, conf=conf, show=True )
